#include "sys_uart.h"
#include "sys_clock.h"
#include "sys_gpio.h"
#include "sys_delay.h"
#include "sys_cache.h"
#include "sys_interrupt.h"
#include "sys_timer.h"
#include "sys_sd.h"
#include "sys_mmu.h"
#include "diskio.h"
#include "ff.h"
#include "string.h"
/*---------------------------------------------------
修改BUG
	2020-09-22
		1.取卡插卡复位启动正常，不取卡复位启动不正常。
			改正方法：SD_Hardware_Reset()硬件复位延时由1ms改为50ms。
		2.读卡速度慢问题，示波器测量读扇区与读扇区中间存在长延时。
			改正方法：sunxi_mmc_send_cmd()中两个1000us延时改为1us延时。
		3.TF卡格式化选择[分配单元大小为64KB]会加快FATFS的写入速度。
			因为单元64KB大小时FATFS会128扇区连续读写,对写速度影响比较大,读速度影响较小。

		FATFS读写
		------------------------------
		Write Count: 13,107,200
		Write Time: 927 ms
		Write Speed: 13,807 KB/S
		------------------------------
		Read Count: 13,107,200
		Read Time: 681 ms
		Read Speed: 18,795 KB/S
		------------------------------
	2020-10-11
		1.增加热插拔检测。SD初始化里发送CMD8后加一个10ms延时，不然会概率性初始化错误。
	2021-02-01
		1.高速卡CPU模式读错误。修改PLL_PERIPH时钟读取不对的问题后正确。
----------------------------------------------------*/

#define SD_DET 1 //=1卡检测使能
/*---------------------------------------------------
---- main
---- main
----------------------------------------------------*/
int SDx = SD0;
#define BUFF_SIZE (1024 * 1024) // 读写缓存大小
__align(4) u8 buff[BUFF_SIZE] = {0};
FATFS fs;
int main(void)
{
#if SD_DET
	int SDInit = 0;
#endif
	int i;
	UINT br;
	FIL fp1;
	DIR dp1;
	Sys_Clock_Init(408000000);
	sys_mmu_init();
	Sys_Uart_Init(UART0, 408000000, 115200, 0);
	sysprintf("\r\n\r\n\r\n");
	sysprintf("Sys_Start...\r\n");
	sysprintf("[2020-09-23]...\r\n");
	sysprintf("Dram Init Size %d Mb.\r\n", 32);
	// 定时器
	Timer1_Init();
#if 0 // 单SD测试
  //SD_Demo1();
	//SD_Demo2();
	SD_Demo3();//SD扇区读写速度测试
#endif

#if SD_DET
	// 卡检测IO初始化
	GPIO_Congif(GPIOE, GPIO_Pin_2, GPIO_Mode_IN, GPIO_PuPd_UP);
	while (1)
	{
		// 检测插入
		if ((GPIO_READ(GPIOE, GPIO_Pin_2) == 0) && (SDInit == 0))
		{
			delay_ms(50); // 消抖
			if ((GPIO_READ(GPIOE, GPIO_Pin_2) == 0) && (SDInit == 0))
			{
				SDInit = 1;
				sysprintf("卡已插入..\r\n");
#endif
				// FATFS测试
				if (f_mount(&fs, "0:", 1) == 0)
				{
					sysprintf("文件系统挂载成功...\r\n");

					if (f_opendir(&dp1, "0:/PicS61234") == 5)
					{
						f_closedir(&dp1);
						sysprintf("没有文件路径,创建..\r\n");
						if (f_mkdir("0:/PicS61234") == 0)
						{
							sysprintf("路径创建成功...\r\n");
						}
					}
					else
					{
						sysprintf("路径存在...\r\n");
					}
					//
					i = f_open(&fp1, "0:/PicS61234/2018.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
					if (i == 5)
						sysprintf("文件夹路径不存在..\r\n");
					if (i == 4)
					{
						sysprintf("文件没有,创建..\r\n");
						i = f_open(&fp1, "0:/PicS61234/2018.txt", FA_CREATE_NEW | FA_WRITE | FA_READ);
					}
					if (i == 0)
					{
						sysprintf("文件打开成功..\r\n");

#if 0 // FATFS写入测试
						if(f_write ( &fp1,"2018-08-15 11:51 \r\n",19,&br)==0)
						{
							sysprintf("文件写入成功..\r\n");
						}
#endif

#if 1 // FATFS读写速度测试
						sysprintf("------------------------------\r\n");
						// 清值
						memset((void *)buff, '0', BUFF_SIZE);
						// FATFS写入速度测试
						i = Read_time_ms();
						if (f_write(&fp1, (UINT8 *)buff, BUFF_SIZE, &br) == 0)
						{
							i = Read_time_ms() - i;
							sysprintf("Write Successful.\r\n");
							sysprintf("Write Count: %d \r\n", br);
							sysprintf("Write Time: %d ms\r\n", i);
							sysprintf("Write Speed: %d KB/S\r\n", (unsigned int)(1000.0 / (float)i * (float)(br / 1024)));
						}
						else
						{
							sysprintf("Write Error.\r\n");
						}
						// FATFS读出速度测试
						sysprintf("------------------------------\r\n");
						f_lseek(&fp1, 0); // 读写偏移到0
						i = Read_time_ms();
						if (f_read(&fp1, (UINT8 *)buff, BUFF_SIZE, &br) == 0)
						{
							i = Read_time_ms() - i;
							sysprintf("Read Successful.\r\n");
							sysprintf("Read Count: %d \r\n", br);
							sysprintf("Read Time: %d ms\r\n", i);
							sysprintf("Read Speed: %d KB/S\r\n", (unsigned int)(1000.0 / (float)i * (float)(br / 1024)));
						}
						else
						{
							sysprintf("Read Error.\r\n");
						}
						sysprintf("------------------------------\r\n");
#endif
						f_close(&fp1);
					}
				}
				else
					sysprintf("没有文件系统..\r\n");

#if SD_DET
			}
		}
		// 检测拔出
		if ((GPIO_READ(GPIOE, GPIO_Pin_2) == 1) && (SDInit == 1))
		{
			SDInit = 0;
			SD_Exit(SD0);
			sysprintf("卡已拔出..\r\n\r\n\r\n");
			delay_ms(50);
		}
	}
#else
	while (1)
	{
	}
#endif
}
